/**
 ** @author: 浓咖啡
 ** @date:  2018.5.29
 ** @brief: 消息处理分发模块
 ** 此线程主要用于从消息缓冲区中分解消息并且分发出去
 ** 还未处理字节序问题
 */

#include "msg_handler.h"
#include "msg_buf.h"
#include "login_handle.h"

static void *start_handler(void *arg);
static struct list_head hand_head;

int init_msg_handler(pthread_t *tid)
{
    int ret;

    INIT_LIST_HEAD(&hand_head);  //初始化每个链表头

    //把各个模块注册进来
    init_login_handle();

    //初始化分发线程
    ret = pthread_create(tid, NULL, start_handler, NULL);
    if(ret < 0){
        err_log("pthread_create err");
        return -1;
    }

    return 0;
}

/**
 * @brief 需要接收消息的注册进来
 * @param obj 需要接收消息的实体
 * @return
 */
void register_handle(struct handle_obj *obj)
{
    list_add(&obj->list, &hand_head);
}

void unregister_handle(struct handle_obj *obj)
{
    list_del(&obj->list);
}


/**
 * @brief 从缓冲区中获取消息，并分发给处理结点
 * 这里还缺少大小端处理
 * @param arg
 * @return
 */
static void *start_handler(void *arg)
{
    int ret;
    MSG_LEN_TYPE len = -1;  //读取数据长度
    MSG_TYPE type;

    struct msg *msg_tmp = NULL;
    struct list_head *pos;
    struct handle_obj *obj_tmp;

    while (1) {
        //1.先读取消息的长度
        ret = msg_read(&len, sizeof(MSG_LEN_TYPE));
        if(ret < 0){
            err_log("msg read err");
            //这里如果一旦读错，后续可能会导致连锁错误
            continue;
        }

        //2.为消息分配合适大小的空间
        msg_tmp = (struct msg *)malloc(sizeof(struct msg) + len);
        msg_tmp->data_len = len;

        //3.读取剩余的消息数据
        ret = msg_read(msg_tmp->data, (len-sizeof(MSG_LEN_TYPE)));
        if(ret < 0){
            err_log("msg read err");
            continue;
        }

        //4.过滤出type
        memcpy(&type, msg_tmp->data, sizeof(MSG_TYPE));
        LOG("recv a msg, len = %d, type = %d", len, type);

        //读取成功后msg_tmp就是本次要处理的一个消息，分发即可。
        list_for_each(pos, &hand_head)
        {
            obj_tmp = list_entry(pos, struct handle_obj, list);
            if(obj_tmp->contain(type)){
                obj_tmp->handler(msg_tmp);
                //处理完后需要释放空间
                free(msg_tmp);
                msg_tmp = NULL;
            }
        }
    }
}

